package com.jide.treetable;

import com.jidesoft.grid.*;
import com.thghh.table.BeanColumn;
import com.thghh.table.BeanColumnAnnotationProcessor;
import com.thghh.table.CheckException;

import java.awt.*;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Zhikang.Peng
 * @version 1.0
 * @email thghh@qq.com
 * @date 2021/1/28 10:16
 */
public class TreeTableDataModel<T extends Row> extends TreeTableModel<T> implements StyleModel {

    protected static CellStyle BOLD = new CellStyle();
    protected Class<T> entityClass;
    protected ExpandableRow root;
    private BeanColumnAnnotationProcessor beanColumnProcessor;

    static {
        BOLD.setFontStyle(Font.BOLD);
    }

    public TreeTableDataModel(Class<T> entityClass) {
        this.entityClass = entityClass;
        this.beanColumnProcessor = new BeanColumnAnnotationProcessor(entityClass);
    }

    public void setDataList(List<T> dataList) {
        setOriginalRows(dataList);
    }

    public void setDataList(T value) {
        setOriginalRows(new ArrayList<>(Arrays.asList(value)));
    }

    @Override
    public void setOriginalRows(List<? extends T> rows) {
        if (entityClass == null)
            return;
        super.setOriginalRows(rows);
    }

    @Override
    public ExpandableRow getRoot() {
        if (root == null) {
            root = (ExpandableRow) super.getRoot();
        }
        return root;
    }

    @Override
    public int getRowCount() {
        return super.getRowCount();
    }

    @Override
    public int getColumnCount() {
        return beanColumnProcessor.getColumnCount();
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Object obj;
        try {
            T data = getRowAt(rowIndex);
            obj = beanColumnProcessor.getPropertyValue(data, columnIndex);
        } catch (Exception e) {
            throw new CheckException(e);
        }
        return obj;
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        try {
            T data = getRowAt(rowIndex);
            Object oldValue = this.getValueAt(rowIndex, columnIndex);
            beanColumnProcessor.setPropertyValue(data, columnIndex, aValue);
            fireTableRowsUpdated(rowIndex, columnIndex);
            data.cellUpdated(columnIndex);
        } catch (Exception e) {
            throw new CheckException(e);
        }
    }

    @Override
    public String getColumnName(int column) {
        return beanColumnProcessor.getBeanColumn(column).name();
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return beanColumnProcessor.getPropertyDescriptor(columnIndex).getPropertyType();
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return beanColumnProcessor.getBeanColumn(columnIndex).editable();
    }

    @Override
    public CellStyle getCellStyleAt(int rowIndex, int columnIndex) {
        Row row = getRowAt(rowIndex);
        if (row.getParent() == getRoot() || (row instanceof ExpandableRow && ((ExpandableRow) row).hasChildren())) {
            return BOLD;
        }
        return null;
    }

    @Override
    public boolean isCellStyleOn() {
        return true;
    }

}
